package com.mew.chess.core.game.shbz.game;

import cn.hutool.core.util.RandomUtil;
import com.mew.chess.core.game.shbz.game.common.*;
import com.mew.chess.core.game.shbz.game.message.TidePushMessage;
import com.mew.common.rest.bo.GameSession;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;

@Slf4j
@Data
@ToString(of = {"roomId", "tableId"})
@NoArgsConstructor
@EqualsAndHashCode(of = {"roomId", "tableId"})
public class ShbzTableManager {
    private static final Logger logger = LoggerFactory.getLogger(ShbzTableManager.class);
    private int roomId;
    private int roomType;
    private int tableId;

    //private int oldTide;

    private int linkType;
    private long startTime;
    private int ruleTime;
    private AtomicInteger fishKeyId = new AtomicInteger(0);
    private byte scenarioNo;
    private Date boss = new Date();

    private final ConcurrentMap<Long, FishUserBO> onlineUserMap = new ConcurrentHashMap<>(16); //userId   v: seatNo
    private final ConcurrentMap<Integer, ShbzSeatManager> seatMap = new ConcurrentHashMap<>(16); //userId v seatmanager
    private final ConcurrentMap<Integer, FishBO> fishMap = new ConcurrentHashMap<>(16); //seaNo userId
    private TidePushMessage tidePushMessage = new TidePushMessage();

    private ShbzScheduleManager shbzScheduleManager;
    private final Semaphore semaphore = new Semaphore(1);

    //记录
    public long playTimes;
    public long dodgeTimes;
    public HashMap<Integer,FishTableLog> logMap = new HashMap<>();  //押注  鱼


    public ShbzTableManager(int roomId, int roomType, int tableId){
        this.roomId = roomId;
        this.roomType = roomType;
        this.tableId = tableId;
        this.shbzScheduleManager = new ShbzScheduleManager(tableId,roomId);
    }

    public boolean checkIsNoStart() {
        return shbzScheduleManager.getFlag().get();
    }

    public void startGame(){
        shbzScheduleManager.start();
    }

    public void sitDown(ShbzSeatManager seatManager){
        seatMap.put(seatManager.getSeatNo(), seatManager);
    }

    public void standUP(byte seatNo){
        seatMap.remove(seatNo);
    }

    public void pushOnlineUserMap(FishUserBO fishUserBO){

        onlineUserMap.put(fishUserBO.getUserId(), fishUserBO);
        int seatNo = fishUserBO.getSeatNo();
        ShbzSeatManager shbzSeatManager = seatMap.get(seatNo);
        FishTableUtil.playerInoutMsg(this, shbzSeatManager, 1);
    }

    public ShbzSeatManager getSeatByUserId(long userId){
        if (null==onlineUserMap.get(userId)){
            return null;
        }
        return seatMap.get(onlineUserMap.get(userId).getSeatNo());
    }

    public List<FishUserBO> getOtherPlayer(long userId){
        return onlineUserMap.values().stream().filter(u -> userId != u.getUserId()).collect(Collectors.toList());
    }

    public boolean emptyTable(){
        return  seatMap.size()  < FishConstantValue.SEAT_NUM;
    }

    public List<Integer> emptyPlayerSeat(){
        List<Integer> list = new ArrayList<>(FishConstantValue.SEAT_NUM);
        for (Integer i = 1; i<= FishConstantValue.SEAT_NUM; i++){
            if (null == seatMap.get(i)){
                list.add(i);
            }
        }
        return list;
    }

    public void clearOnlineUser(long userId){
        seatMap.remove(getSeatByUserId(userId));
        onlineUserMap.remove(userId);
    }

    public void exitGameTable(long userId){
        ShbzSeatManager seatManager = getSeatByUserId(userId);
        if (null == seatManager){
            return;
        }

        FishTableUtil.playerInoutMsg(this, seatManager,  0);
        onlineUserMap.remove(userId);
        seatMap.remove(seatManager.getSeatNo());
        stopGame();

    }

    public void lostConnection(long uid){
        GameSession session = getOnlineUserMap().get(uid).getGameSession();
        if (null==session||session.isWeakClose()){
            ShbzSeatManager seatManager = getSeatByUserId(uid);
            if (null == seatManager){
                return;
            }
            FishTableUtil.playerInoutMsg(this, seatManager,  0);
            onlineUserMap.remove(uid);
            seatMap.remove(seatManager.getSeatNo());
        }

    }

    public void stopGame(){
        if (onlineUserMap.isEmpty()){
            // TODO 停止捕鱼
            shbzScheduleManager.stop();
            linkType = FishLinkType.Prepare.code();

        }

    }

    public void allFishClear(){
        fishKeyId.set(1);
        scenarioNo = (byte) RandomUtil.randomInt(FishConstantValue.SCENARIO_LENGTH);
        //
        boss = new Date();
        //清楚鱼
        fishMap.clear();
    }

    public void fishClear(){
        fishKeyId.set(1);
        boss = new Date();
        //清楚鱼
        fishMap.clear();
    }

    public void deadFish(){
        for (Integer k : fishMap.keySet()) {
            FishBO fishBO = fishMap.get(k);
            if (fishBO.getRemainStep()*FishConstantValue.STEP_TIME>=fishBO.getRuleStep()){
                //行走步长大于会定步长
                fishMap.remove(k);
            }
        }
    }

    public boolean bossTime(){

        if (boss==null || boss.getTime()==0){
            boss = new Date();
            return false;
        }

        if (System.currentTimeMillis()-boss.getTime()>FishConstantValue.fishRedisValue.boss_tide){
            boss = new Date();
            return true;
        }

        return false;
    }

    public FishTableLog getFishTablelog(int fishType){
        FishTableLog fishTableLog = this.logMap.get(fishType);
        if (null==fishTableLog){
            fishTableLog = new FishTableLog();
            logMap.put(fishType,fishTableLog);
        }

        return fishTableLog;
    }

}
